/**
 * @file t_at.c
 * @brief This is the source file for t_at.c, which is the porting file for the AT command module.
 * @version 1.0
 * @date 2024-10-15
 * @history
 * <---------------------------------------------------------------------------------->
 * + func t_at_send_and_wait()  failed to (re)send,clear buffer @date 2024-10-16
 * + fix  uising free rtos event——ISR ERRO |Error:..\FreeRTOS\portable\RVDS\ARM_CM4F\port.c,872|
 * + @see https://blog.csdn.net/wuwenbin12/article/details/119420845
 * <---------------------------------------------------------------------------------->
 */
#include "t_at.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

#include "t_at_urc_etgp.h"
// no using
void t_at_trim(uint8_t *strIn)
{
    int i, j;
    i = 0;
    j = strlen((char *)strIn) - 1;

    while (strIn[i] == '\r' || strIn[i] == '\n')
    {
        i++;
    }
    while (strIn[j] == '\r' || strIn[j] == '\n')
    {
        j--;
    }
    memmove(strIn, strIn + i, j - i + 1);
    strIn[j - i + 1] = '\0';
}

void t_at_clear(t_at_t *me, uint8_t sel_clear)
{
    if (me == T_NULL)
    {
        return;
    }
    // unsigned char i = RCV_BUFFER_SIZE-1;
    // while(i--)
    // {
    //     me->rvbuffer[i] = 0;
    // }
    if (sel_clear == 0) 
    {
        memset(me->buffer->rvbuffer, 0, RCV_BUFFER_SIZE);
        memset(me->buffer->ucr_cmd_buffer, 0, URC_CMD_BUFFER_SIZE);
    }
    if (sel_clear == 1)
    {
        memset(me->buffer->prabuffer, 0, RCV_BUFFER_SIZE);
    }
}

void t_at_destroy(t_at_t *me)
{
    if (me == T_NULL)
    {
        return;
    }
    if (me->buffer != T_NULL)
    {
        AT_FREE(me->buffer);
    }
    AT_FREE(me);

}
/**
 * @brief This function is used to create an AT object.
 * @param t_send The function pointer for sending AT commands.
 * @param urc_handle The function pointer for handling URC (Unsolicited Result Code) events.
 * @param attempts_waittime The wait time for attempts.
 * @param NubResend The number of resend attempts.
 * @return A pointer to the created AT object.
 * @note This function allocates memory for the AT object and its buffer.
*/
t_at_t *t_at_create(t_at_send t_send, t_at_urc_callback urc_handle, uint32_t attempts_waittime, uint8_t NubResend)
{
    t_at_t *me = (t_at_t *)AT_MALLOC(sizeof(t_at_t));

    if (me)
    {
        me->send_cmds_time=100; // default send time
        me->t_send = t_send;
        me->urc_handle = urc_handle;
        me->attempts_waittime = attempts_waittime;
        me->NubResend = NubResend;
        me->buffer = (at_buffer_t *)AT_MALLOC(sizeof(at_buffer_t));
        if (me->buffer == T_NULL)
        {
            AT_DEBUG("t_at_create —ERRO\n");
            AT_FREE(me);
            return T_NULL;
        }
        AT_DEBUG("t_at_create\n");
    }
    return me;
}
/**
 * @brief This function is used to set this user arg,if you want to use URC_ETGP  module.
 * @param me The AT object.
 * @param urc_arg The user argument to be set.
*/
T_ErrType t_at_set_URC_userarg(t_at_t *me, void *urc_arg)
{
    if (me == T_NULL || urc_arg == T_NULL)
    {
        return FUN_Err;
    }
    me->urc_arg = urc_arg;
    return FUN_OK;
}

/**
 * @brief This function is used to add in OS object for the AT command module.
 * @param me The AT object.
 * @param os The OS object （Event Groups）.Useing FreeRTOS API to dealy AT.
 * @param os_init The function pointer for initializing the OS object.
 * @param os_lock The function pointer for locking the OS object.
 * @param os_unlock The function pointer for unlocking the OS object.
 * @return The result of the operation.
 * @note This function initializes the OS object and sets the function pointers for locking and unlocking @see t_at_port.c.
*/
T_ErrType t_at_os_add(t_at_t *me, void *os, t_at_os_init os_init, t_at_os_lock os_lock, t_at_os_unlock os_unlock)
{
    T_OSLokType ret;
    if (me == T_NULL || os_init == T_NULL || os_lock == T_NULL || os_unlock == T_NULL)
    {
        return FUN_Err;
    }
    me->os = os;
    me->os_init = os_init;
    me->os_lock = os_lock;
    me->os_unlock = os_unlock;
    ret = me->os_init(me->os);//初始化你的信号量的操作
    if (ret != T_OS_OK)
    {
        return FUN_Err;
    }
    return AT_OK;
}
/**
 * @brief This function is used to add in ring buffer for the AT command module.
 * @param me The AT object.
 * @param rbufer The ring buffer object.
 * @param rbf_init_F The function pointer for initializing the ring buffer.
 * @param rbf_push_F The function pointer for pushing data into the ring buffer.
 * @param rbf_pop_F The function pointer for popping data from the ring buffer.
 * @param rbf_clear_F The function pointer for clearing the ring buffer.
 * @param rbf_is_empty_F The function pointer for checking if the ring buffer is empty.
 * @param rbf_is_full_F The function pointer for checking if the ring buffer is full.
 * @return The result of the operation.
 * @note This function initializes the ring buffer and sets the function pointers for its operations.
*/

T_ErrType t_at_ringbuffer_add(t_at_t *me,
                                 rbuf *rbufer,
                                 t_at_rbuf_init rbf_init_F,
                                 t_at_rbuf_push rbf_push_F,
                                 t_at_rbuf_pop rbf_pop_F,
                                 t_at_rbuf_clear rbf_clear_F,
                                 t_at_rbuf_is_empty rbf_is_empty_F,
                                 t_at_rbuf_is_full rbf_is_full_F)
{
    if (me == T_NULL || rbf_init_F == T_NULL || rbf_push_F == T_NULL ||
        rbf_pop_F == T_NULL || rbf_clear_F == T_NULL ||
        rbf_is_empty_F == T_NULL || rbf_is_full_F == T_NULL)
    {
        return FUN_Err;
    }
    me->rbufer = rbufer;
    me->rbuf_init = rbf_init_F;
    me->rbuf_push = rbf_push_F;
    me->rbuf_pop = rbf_pop_F;
    me->rbuf_clear = rbf_clear_F;
    me->rbuf_is_empty = rbf_is_empty_F;
    me->rbuf_is_full = rbf_is_full_F;
    me->rbuf_init(me->rbufer);
    return FUN_OK;
}
/**
 * @brief This function is used to add  HW-send-interface for the AT command module.
 * @param: me[in] at objects.
 *  @param: hw_send[in] HW-send-interface.
*/
T_ErrType t_at_send_add(t_at_t *me, t_at_send hw_send)
{
    if (me == NULL || hw_send == NULL) {
        return FUN_Err;
    }
    
    me->t_send = hw_send;
    return AT_OK;
}
//NO --ringbuffer
T_ErrType t_at_rev_data_push(t_at_t *me, uint8_t *buffer, uint16_t len)
{
    if (me == T_NULL || buffer == T_NULL)
    {
        return FUN_Err;
    }
    memset(me->buffer->rvbuffer, 0, RCV_BUFFER_SIZE);
    memcpy(me->buffer->rvbuffer, buffer, len);
    if (strstr((char *)buffer, "+QMTRECV"))
    {                                               // 需要实现一个 ucr分拣器
        memcpy(me->buffer->prabuffer, buffer, len); /*shadow space  for  data buffer*/
    }
    AT_DEBUG("t_at_rePushSet:%s\n", me->at_buffer_t->rvbuffer);
    /**/
#if T_AT_RTOS_EN /*useing os*/

    if (me->os_unlock(me->os) != T_OS_OK)
    {
        return FUN_Err;
    }
#endif
    return AT_OK;
}

/**
 * @brief This function is used to push data into the ring buffer.
 * @param me The AT object.
 * @param buffer The data buffer.
 * @param len The length of the data.
 * @param cmd_UrcString The URC string to be checked.
 * @return The result of the operation.
 * @note This function checks if the ring buffer is full before pushing data into it.
 * If the buffer is full, it will not push the data.
*/
rdata_buff rpbuf_data = {0};
T_ErrType t_at_rev_push_data_rbf(t_at_t *me, uint8_t *buffer, uint16_t len,char *cmd_UrcString)
{
    
    T_ErrType ret = AT_OK;
    if (me == T_NULL || buffer == T_NULL || me->rbufer == T_NULL)
    {
        return FUN_Err;
    }
    memset(me->buffer->rvbuffer, 0, RCV_BUFFER_SIZE);
    memset(me->buffer->ucr_cmd_buffer, 0, URC_CMD_BUFFER_SIZE);
    memcpy(me->buffer->rvbuffer, buffer, len);
    if (strstr((char *)buffer,cmd_UrcString))
    {                                          // 需要实现一个 ucr分拣器一直都没完成不过不需要了
        memcpy(rpbuf_data.buffer, buffer, len); /*shadow space  for  data buffer*/
        rpbuf_data.buf_len = len;
        if (me->rbuf_is_full(me->rbufer) == RBUF_FULL)
        {
            AT_DEBUG("rbuf is full \n");
        }
        else
            me->rbuf_push(me->rbufer, &rpbuf_data);

        AT_DEBUG("t_at_rev_push_rbf:%s...len %d\n", rpbuf_data.buffer, rpbuf_data.buf_len);
    }
#if URC_EN /*URC回调，不需要检测，失能即可*/
    memcpy(me->buffer->ucr_cmd_buffer, buffer, len);
    urc_thread_push_ISR(me,me->buffer->ucr_cmd_buffer,len); /*压入数据到URC环形缓冲区*/
#endif
    /**/
#if T_AT_RTOS_EN /*useing os*/

    if (me->os_unlock(me->os) != T_OS_OK)
    {
        return FUN_Err;
    }
#endif
    return ret;
}
/**
 * @brief This function is used to add delay-fn for the AT object.
 * @param: me[in] at objects.
 *  @param: t_at_deay[in] delay-fn.
*/
T_ErrType t_at_delay_add(t_at_t *me,t_at_delay delay_t)
{
  if(me==T_NULL){
    return FUN_Err;
  }
  me->at_delay=delay_t;
  return AT_OK;
}

T_ErrType t_at_send_and_wait(t_at_t *me, uint16_t data_len, char *CMD, char *CMD_UCR,uint32_t cmd_send_s, uint32_t waittime)
{   
    #if T_AT_RTOS_EN //大于0的时间使用send cmd 间隔小于0的直接发送
    if(me->send_cmds_time > 0)
    {
        me->at_delay(cmd_send_s); /*delay 1ms*/
    }
    me->t_send(me, (uint8_t *)CMD, data_len);
    #else
     if(me->send_cmds_time > 0)
    {
        t_longdelay(cmd_send_s); /*delay 1ms*/
    }
    me->t_send(me, (uint8_t *)CMD, data_len);
    #endif
    uint32_t cur_time_start = t_at_get_tick();
    T_ErrType ret = AT_OK;
    while (1)
    {
// printf("...........................................\n");
#if T_AT_RTOS_EN                                          /*useing os*/
        if (me->os_lock(me->os, waittime) == T_OS_TIMOUT) /*Release cpu control permissions*/
        {
            AT_DEBUG("t_at_cmd_send:AT_TIMEOUT\n");
            if (me->NubResend > 1)
            {
                AT_DEBUG("AT send CMD  multi  AT_TIMEOUT\n");
                t_at_clear(me, 0);       // failed to resend,clear buffer
                ret = AT_RESEND_TIMEOUT; // second inter timeout
            }
            else
            {
                AT_DEBUG("AT send  CMD once AT_TIMEOUT\n");
                t_at_clear(me, 0); // failed to send ,clear buffer
                ret = AT_TIMEOUT;  // first inter timeout
            }
            break;
        }
        else
        {
            if (strstr((char *)me->buffer->rvbuffer, CMD_UCR))
            {
                int str_len = strlen((char *)me->buffer->rvbuffer);
                me->urc_handle(me, me->buffer->rvbuffer, str_len, (uint8_t *)CMD_UCR);
                AT_DEBUG("t_at_cmd_send:AT_OK\n");
                t_at_clear(me, 0);
                ret = AT_OK;
                break;
            }
        }
#else /*no-rtos*/
        if (t_at_get_tick() - cur_time_start > waittime)
        {
            AT_DEBUG("t_at_cmd_send:AT_TIMEOUT\n");
            if (me->NubResend > 0)
            {
                AT_DEBUG("AT send CMD  multi  AT_TIMEOUT\n");
                ret = AT_RESEND_TIMEOUT; // second inter timeout
            }
            else
            {
                AT_DEBUG("AT send  CMD once AT_TIMEOUT\n");
                ret = AT_TIMEOUT; // first inter timeout
            }
            break;
        }

        if (strstr((char *)me->buffer->rvbuffer, CMD_UCR))
        {
            me->urc_handle(me, me->buffer->rvbuffer, (uint8_t *)CMD_UCR);
            AT_DEBUG("t_at_cmd_send:AT_OK\n");
            t_at_clear(me);
            ret = AT_OK;
            break;
        }
#endif
    }
    return ret;
}
/*+if(phandle!=NULL)
        {
    me->urc_handle = phandle;
        }
判断if NULL使用固定的caballk ;

+datalen
*/
T_ErrType t_at_cmd_send(t_at_t *me, uint16_t data_len, char *CMD, char *CMD_UCR, t_at_urc_callback phandle, uint32_t waittime, uint8_t resendCount)
{
    if (me == T_NULL || CMD == T_NULL || CMD_UCR == T_NULL)
    {
        return FUN_Err;
    }
    T_ErrType ret = AT_OK;
    if (phandle != T_NULL)
    {
        me->urc_handle = phandle;
    }
    strcpy((char *)me->buffer->ucr_cmd_buffer, CMD_UCR);
    // No resend
    if (resendCount <= 1)
    {
        ret = t_at_send_and_wait(me, data_len, CMD, (char *)me->buffer->ucr_cmd_buffer,me->send_cmds_time, waittime);
    }
    // Resend
    else
    {
        for (uint8_t i = 0; i < resendCount; i++)
        {
            ret = t_at_send_and_wait(me, data_len, CMD, (char *)me->buffer->ucr_cmd_buffer,me->send_cmds_time ,waittime);
            if (ret == AT_OK)
            {
                AT_DEBUG("t_at_cmd_send: .%d AT_OK\n", i);
                break;
            }
        }
    }
    return ret;
}
///设置正常收发的回调函数
T_ErrType t_at_urc_callback_set(t_at_t *me, t_at_urc_callback urc_callback)
{
    if (me == T_NULL || urc_callback == T_NULL)
    {
        return FUN_Err;
    }
    me->Par_urc_callback = urc_callback;
    return FUN_OK;
}
//设置发送指令的间隔
T_ErrType t_at_send_time_set(t_at_t *me, uint32_t sp_time)
{
    if (me == T_NULL)
    {
        return FUN_Err;
    }
    me->send_cmds_time = sp_time;
    return FUN_OK;
}
//单个的解析
T_ErrType t_at_parse_polling(t_at_t *me, uint8_t *URC)
{
    if (me == T_NULL || URC == T_NULL)
    {
        return FUN_Err;
    }
    if (strstr((char *)me->buffer->prabuffer, (char *)URC))
    {
        int str_len = strlen((char *)me->buffer->prabuffer);
        me->Par_urc_callback(me, me->buffer->prabuffer, str_len, URC); // 数字没用
        AT_DEBUG("t_at_parse_polling:AT_OK\n");
        t_at_clear(me, 1);
        return URC_FIND;
    }
    return URC_NOT_FIND;
}
rdata_buff rbuf_data = {0};
/**
 * @brief This function is used to parse the polling data from the ring buffer.
 * @param me The AT object.
 * @param URC The URC string to be checked.
 * @return The result of the operation.
 * @note This function checks if the ring buffer is empty before parsing the data.
 * If the buffer is empty, it will not parse the data.
 */
T_ErrType t_at_parse_polling_rbf(t_at_t *me, uint8_t *URC)
{
    if (me == T_NULL || URC == T_NULL)
    {
        return FUN_Err;
    }
    if (me->rbuf_is_empty(me->rbufer) != RBUF_EMPTY)
    {
        me->rbuf_pop(me->rbufer, &rbuf_data);
        if (strstr((char *)rbuf_data.buffer, (char *)URC))
        {
            me->Par_urc_callback(me, rbuf_data.buffer, rbuf_data.buf_len, URC);
            AT_DEBUG("t_at_parse_polling_rbf:AT_OK\n");
            t_at_clear(me, 1);
            return URC_FIND;
        }
    }

    return URC_NOT_FIND;
}
/**
 * @brief AT命令格式化封装
 * @param output 输出缓冲区
 * @param out_size 输出缓冲区大小
 * @param out_len 返回实际长度
 * @param fmt 格式化字符串（如"AT+CMD=%d"）
 * @param ... 可变参数
 * @return 0成功，非零失败
 */
uint16_t AT_CMD_FORMAT(char *output, uint16_t out_size, uint16_t *out_len, const char *fmt, ...)
{
    /* 参数检查 */
    if (!output || !out_len || !fmt || out_size == 0) {
        return 1; // 参数错误
    }

    /* 安全清空缓冲区 */
    memset(output, 0, out_size);

    /* 格式化处理 */
    va_list args;
    va_start(args, fmt);
    int len = vsnprintf(output, out_size, fmt, args);
    va_end(args);

    /* 错误处理 */
    if (len <= 0) {
        *out_len = 0;
        return 2; // 格式化失败
    }
    if ((uint16_t)len >= out_size) {
        *out_len = 0;
        return 3; // 缓冲区不足
    }

    *out_len = (uint16_t)len;
    return 0; // 成功
}

//挂载Ring Buffer
void t_at_urc_ringbuffer_add(t_at_t *me, rbuf *urc_rbuf)
{
    if (me == T_NULL || urc_rbuf == T_NULL) {
        return;
    }
    me->urc_rbufer = urc_rbuf;     // 挂载URC环形缓冲区
    rbuf_init(urc_rbuf);    // 初始化URC环形缓冲区
}

/*1ms*/
void t_at_1ms_cycle(void)
{
    t_at_1ms();
}
